package com.feicheng.house.controller;

import java.time.Clock;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.feicheng.house.entity.Permission;
import com.feicheng.house.entity.Role;
import com.feicheng.house.entity.RolePermission;
import com.feicheng.house.entity.User;
import com.feicheng.house.entity.UserRole;
import com.feicheng.house.exception.SystemException;
import com.feicheng.house.result.ResultInfo;
import com.feicheng.house.service.IPermissionService;
import com.feicheng.house.service.IRolePermissionService;
import com.feicheng.house.service.IRoleService;
import com.feicheng.house.service.IUserRoleService;
import com.feicheng.house.service.IUserService;

@RestController
@RequestMapping("/house/system")
public class SystemController {
	
	@Autowired
	IUserService iUserService;
	
	@Autowired
	IRoleService iRoleService;
	
	@Autowired
	IPermissionService iPermissionService;
	
	@Autowired
	IUserRoleService iUserRoleService;
	
	@Autowired
	IRolePermissionService iRolePermissionService;
	
	@PutMapping("/login")
	public ResultInfo login(User user, HttpServletRequest request) {
		
//		１．パラメータチェック		
//		１．１、入力「用户情報Bean.账户名」が入力しない場合	
		if (StringUtils.isEmpty(user.getAccount())) {
//			メーセージ「E002」が「システム例外」として発生する。
			throw new SystemException("账户名必须输入");
		}
		
//		１．２、入力「用户情報Bean.密码」が入力しない場合
		if (StringUtils.isEmpty(user.getPassword())) {
//			メーセージ「E002」が「システム例外」として発生する。
			throw new SystemException("密码必须输入");
		}
		
/*		２、用户情報を検索する。					
		2.1.下記のSQL文により、用户情報リストを取得する。				
			■検索項目：			
				ユーザ番号		
				账户名		
				密码		
				昵称		
				年龄		
				电话		
				身份证号		
				头像		
				微信OPEN_ID		
				追加者番号		
				追加時間		
				更新者番号		
				更新時間		
			■検索対象テーブル：			
				用户情報（user）		
			■検索条件：			
				用户情報．账户名＝入力「用户情報Bean.账户名」	*/	
		QueryWrapper<User> qw = new QueryWrapper<User>();
		qw.eq("account", user.getAccount());
		List<User> resultList = iUserService.list(qw);
		
//		2.2	上記の取得データ件数＝０の場合
		if (resultList == null || resultList.size() == 0) {
//			メーセージ「用户名不存在」が「システム例外」として発生する。
			throw new SystemException("账户不存在"); 
		
//		2.3	上記の取得データ件数>1の場合
		} else if (resultList.size() > 1) {
//			メーセージ「用户名非法，相关资源将会在30秒后冻结，请联系管理员。」が「システム例外」として発生する。
			throw new SystemException("数据异常，系统将在30秒后冻结相关资源，请联系管理员。"); 
		}
		
//		2.4	上記の取得データ件数=1の場合 取得データが変数「currentUser]に保存する。
		User currentUser = resultList.get(0);
		
//		3	密码チェック
//		変数「currentUser].密码と入力「用户情報Bean.密码」同じないの場合は
		if (!currentUser.getPassword().equals(user.getPassword())) {
//			メーセージ「密码错误」が「システム例外」として発生する。
			throw new SystemException("密码错误");
		}
		
//		4	登録後処理
//		変数「CURRENT_USER_INFO」（MAP）初期化する。
		JSONObject CURRENT_USER_INFO = new JSONObject();
//		変数「currentUser.密码]にNULLを設定する
		currentUser.setPassword(null);
//		変数「currentUser]がVALUEとして定数「user」がキーとして変数「CURRENT_USER_INFO」に保存する。	
		CURRENT_USER_INFO.put("user", currentUser);

/*		■検索項目：		
			ユーザ番号	
			角色编号	
		■検索対象テーブル：		
			用户角色（user_role）	
		■検索条件：		
			用户角色．ユーザ番号＝変数「currentUser].ユーザ番号	*/
		QueryWrapper<UserRole> qwUr = new QueryWrapper<UserRole>();
		qwUr.eq("user_id", currentUser.getUserId());
		
//		取得データが変数「userRoleList」を保存する。
		List<UserRole> userRoleList = iUserRoleService.list(qwUr);
		
//		変数「roleIds」（SET）初期化する。
		Set<Integer> roleIds = new HashSet<Integer>();
		
//		変数「userRoleList」が繰り返し
		for (UserRole ur : userRoleList) {
//			該当データの項目「roleId」が変数「roleIds」に追加する
			roleIds.add(ur.getRoleId());
		}

/*		■検索項目：	
			角色编号
			角色名字
			状态
		■検索対象テーブル：	
			角色情報（role）
		■検索条件：	
			角色情報．角色编号 in 変数「roleIds」*/
		QueryWrapper<Role> qwR = new QueryWrapper<Role>();
		qwR.in("role_id", roleIds);
		
//		取得データが変数「roleList」を保存する。
		List<Role> roleList = iRoleService.list(qwR);
		
/*		■検索項目：	
			角色编号
			权限编号
		■検索対象テーブル：	
			角色权限（role_permission）
		■検索条件：	
			角色权限．角色编号 in 変数「roleList」*/
		QueryWrapper<RolePermission> qwRp = new QueryWrapper<RolePermission>();
		qwRp.in("role_id", roleIds);
		
//		取得データが変数「rolePermissionList」を保存する。
		List<RolePermission> rolePermissionList = iRolePermissionService.list(qwRp);
		
//		変数「permissionIds」（SET）初期化する。
		Set<Integer> permissionIds = new HashSet<Integer>();
		
//		変数「rolePermissionList」が繰り返し
		for (RolePermission rp : rolePermissionList) {
//			該当データの項目「pId」が変数「permissionIds」に追加する
			permissionIds.add(rp.getPermissionId());
		}
		
		/* ■検索項目：	
				权限编号
				权限名字
				状态
				权限内容
				父级权限ID
				图标
			■検索対象テーブル：	
				权限情報（permission）
			■検索条件：	
				权限情報．权限编号 in 変数「permissionIds」 
			■排序：升序   */
		QueryWrapper<Permission> qwP = new QueryWrapper<Permission>();
		
		if (!permissionIds.isEmpty()) {
			qwP.in("permission_id", permissionIds);
		}
		qwP.eq("statu", true);
		qwP.orderByAsc("p_id");
		
//		取得データが変数「permissionList」を保存する。
		List<Permission> permissionList = iPermissionService.list(qwP);
		
//		変数「pList」（LIST）初期化する。
		List<Permission> pList = new ArrayList<Permission>();
		
//		変数「permissionMap」（MAP）初期化する。
		Map<Integer, Permission> permissionMap = new HashMap<Integer, Permission>();
		
//		変数「permissionList」が繰り返し
		for (Permission p : permissionList) {
			
//			該当データの項目「farcherId」がゼロの場合は
			if (0 == p.getpId()) {
//				該当データの項目「pId」がキー、該当データがVALUEとして変数「permissionMap」に追加する
				permissionMap.put(p.getPermissionId(), p);
//				該当データが変数「pList」に追加する
				pList.add(p);
//			それ以外の場合は
			} else {
//				該当データの項目「farcherId」がキーとして変数「permissionMap」から親权限情報の子权限LISTを取得する
				List<Permission> subPList = 
						permissionMap.get(p.getpId()).getSubPermissions();
//				子权限LISTがNULLの場合は
				if (null == subPList) {
//					子权限LISTが初期化する（LIST）
					subPList = new ArrayList<Permission>();
//					親权限情報の子权限LISTを保存する
					permissionMap.get(p.getpId()).setSubPermissions(subPList);
				}
//				該当データが子权限LISTに追加する
				subPList.add(p);
			}
		}
		
//		変数「roleList]がVALUEとして定数「roles」がキーとして変数「CURRENT_USER_INFO」に保存する。	
		CURRENT_USER_INFO.put("roles", roleList);
//		変数「pList]がVALUEとして定数「permissions」がキーとして変数「CURRENT_USER_INFO」に保存する。	
		CURRENT_USER_INFO.put("permissions", pList);
		
//		変数「CURRENT_USER_INFO」がセッションに追加する
		HttpSession session = request.getSession();
		session.setAttribute("CURRENT", CURRENT_USER_INFO);
		
		System.out.println(session.getId());
		
//		変数「CURRENT_USER_INFO」が戻ります。
		return ResultInfo.success(CURRENT_USER_INFO);
	}

	@PostMapping("/register") 
	public ResultInfo register(User user) {

//		１．パラメータチェック
//		１．１、入力「用户情報Bean.账户名」が入力しない場合									
		if (StringUtils.isEmpty(user.getAccount())) {
//			メーセージ「E002」が「システム例外」として発生する。
			throw new SystemException("E002"); 
		}
//		１．２、入力「用户情報Bean.密码」が入力しない場合
		if (StringUtils.isEmpty(user.getPassword())) {
//		メーセージ「E002」が「システム例外」として発生する。
			throw new SystemException("E002"); 
		}
//		１．３、入力「用户情報Bean.电话」が入力しない場合
		if (StringUtils.isEmpty(user.getTel())) {
//			メーセージ「E002」が「システム例外」として発生する。
			throw new SystemException("E002"); 
		}
//		１．４、入力「用户情報Bean.身份证」が入力しない場合	
		if (StringUtils.isEmpty(user.getSecId())) {
//			メーセージ「E002」が「システム例外」として発生する。
			throw new SystemException("E002"); 
		}
		
		QueryWrapper<User> qw = new QueryWrapper<User>();
		qw.eq("account", user.getAccount());
		List<User> resultList = iUserService.list(qw);
		if (resultList != null && resultList.size() > 0) {
			throw new SystemException("用户名已经存在"); 
		}

//		２、用户情報挿入する。
//		２．１、用户情報が追加する
//		システム当前時間取得して、変数「当前時間」が保存する。
		LocalDateTime currentTime = LocalDateTime.now(Clock.system(ZoneId.of("Asia/Shanghai")));
//		入力「ユーザ情報Bean.追加者番号」に変数「0」が設定する。	
		user.setCu(0);
//		入力「ユーザ情報Bean.更新者番号」に変数「0」が設定する。	
		user.setUu(0);
//		入力「ユーザ情報Bean追加時間」に変数「当前時間」が設定する。
		user.setCt(currentTime);
//		入力「ユーザ情報Bean.更新時間」に変数「当前時間」が設定する。
		user.setUt(currentTime);
		
//		入力「ユーザ情報Bean」がパラメータとして、IUserServiceからユーザ情報追加関数を呼び出す。								
		iUserService.save(user);

//		３、戻ります。
		return ResultInfo.success();
	}
	
}
